#include <rtthread.h>
#include <drivers/usb_host.h>

int rt_usb_hcd_alloc_pipe(uhcd_t hcd, upipe_t* pipe, uinst_t inst, uep_desc_t ep)
{
    *pipe = (upipe_t)rt_malloc(sizeof(struct upipe));
    if(*pipe == RT_NULL)
    {
        return -1;
    }

    rt_memset(*pipe,0,sizeof(struct upipe));
    (*pipe)->inst = inst;
    rt_memcpy(&(*pipe)->ep, ep, sizeof(struct uendpoint_descriptor));
    return hcd->ops->open_pipe(hcd, *pipe);
}

int rt_usb_hcd_free_pipe(uhcd_t hcd, upipe_t pipe)
{
    RT_ASSERT(pipe != RT_NULL);
    hcd->ops->close_pipe(hcd, pipe);
    rt_free(pipe);

    return 0;
}

int rt_usb_hcd_setup_xfer(uhcd_t hcd, upipe_t pipe, ureq_t setup, int timeout)
{
    return hcd->ops->pipe_xfer(hcd, pipe, USBH_PID_SETUP, (void *)setup, 8, timeout);
}

int rt_usb_hcd_port_reset(uhcd_t hcd, rt_uint8_t port)
{
    return hcd->ops->reset_port(hcd, port);
}

int rt_usb_hcd_pipe_xfer(uhcd_t hcd, upipe_t pipe, void* buffer, int nbytes, int timeout)
{
    rt_size_t remain_size;
    rt_size_t send_size;
    remain_size = nbytes;
    rt_uint8_t * pbuffer = (rt_uint8_t *)buffer;
    do
    {
        RT_DEBUG_LOG(RT_DEBUG_USB,("pipe transform remain size,: %d\n", remain_size));
        send_size = (remain_size > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : remain_size;
        if(hcd->ops->pipe_xfer(hcd, pipe, USBH_PID_DATA, pbuffer, send_size, timeout) == send_size)
        {
            remain_size -= send_size;
            pbuffer += send_size;
        }
        else
        {
            return 0;
        }
    }while(remain_size > 0);

    return nbytes;
}
